package com.bonc.apicreator.ctrl;


import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.bonc.apicreator.constant.BaseConstant;
import com.bonc.apicreator.dao.ApiDao;
import com.bonc.apicreator.dao.ApiRequestDao;
import com.bonc.apicreator.dao.ApiResponseDao;
import com.bonc.apicreator.dao.ProjectDao;
import com.bonc.apicreator.dao.RowKeyDao;
import com.bonc.apicreator.dao.SqlDao;
import com.bonc.apicreator.entity.Project;
import com.bonc.apicreator.entity.RestApi;
import com.bonc.apicreator.entity.RestApiRequest;
import com.bonc.apicreator.entity.RestApiResponse;
import com.bonc.apicreator.entity.RowKey;
import com.bonc.apicreator.entity.SqlSentence;
import com.bonc.apicreator.utils.JsonUtils;
import com.fasterxml.jackson.core.type.TypeReference;


/**
 * 包含request和response的controller
 *
 * @author gaopengyu
 * @version 2016年8月4日
 * @see ApiDetailController
 * @since
 */
@Controller
@RequestMapping("/api/{apiId}")
public class ApiDetailController {
    /**
     * 日志对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ApiDetailController.class);

    /**
     * request的dao层
     */
    @Autowired
    private ApiRequestDao requestDao;

    /**
     * response的dao层
     */
    @Autowired
    private ApiResponseDao responseDao;

    /**
     * dao
     */
    @Autowired
    private ApiDao apiDao;

    /**
     * dao
     */
    @Autowired
    private ProjectDao projectDao;

    /**
     * RowKeyDao
     */
    @Autowired
    private RowKeyDao rowKeyDao;

    /**
     * sqlDao
     */
    @Autowired
    private SqlDao sqlDao;
    
    /**
     * Description: 加载页面
     * 
     * @return String
     * @see
     */
    @RequestMapping(value = {"/request/detail"})
    public String detail(Model model, @PathVariable Long apiId) {
        RestApi api = apiDao.findOne(apiId);
        String count = "count";
        RestApiResponse response = responseDao.findByApiIdAndDataType(apiId, count);
        /**
         * 如果选择了count且没有生成过count 就生成一个count返回值
         */
        if(api.getResponseDataType().equals(count)&&StringUtils.isEmpty(response)){
            RestApiResponse restApiResponse = new RestApiResponse();
            restApiResponse.setApiId(apiId);
            restApiResponse.setCode("count");
            restApiResponse.setDescription("返回查询总数");
            restApiResponse.setColumnName("");
            restApiResponse.setType("int");
            restApiResponse.setDataType("count");
            responseDao.save(restApiResponse);
        }
        
        String apiName = api.getName();
        Long proId = api.getProId();
        Project project = projectDao.findOne(proId);
        String proName = project.getName();
        RowKey rowKey = rowKeyDao.findByApiId(apiId);
        if (!StringUtils.isEmpty(rowKey)) {
            model.addAttribute("rowkey", rowKey);
        }
        SqlSentence sqlSentence = sqlDao.findByApiId(apiId);
        if (!StringUtils.isEmpty(sqlSentence)) {
            model.addAttribute("sqlSentence", sqlSentence);
        }   
        model.addAttribute("api", api);
        model.addAttribute("proId", proId);
        model.addAttribute("apiName", apiName);
        model.addAttribute("proName", proName);
        model.addAttribute("apiId", apiId);
        model.addAttribute("project", project);
        return "/api/detail.jsp";
    }

    /**
     * Description:
     * 
     * @param model
     * @param apiId
     * @return String
     * @see
     */
    @RequestMapping(value = {"/request/list"})
    @ResponseBody
    public String request(Long apiId) {
        List<RestApiRequest> list = requestDao.findByApiIdOrderByDataTypeDesc(apiId);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", BaseConstant.STATE_SUCCESS);
        map.put("list", list);
        LOGGER.debug(JSON.toJSONString(list));
        return JSON.toJSONString(map);
    }

    /**
     * Description: 保存request信息
     * 
     * @param apiRequest
     * @param apiId
     * @return String
     * @see
     */
    @RequestMapping(value = {"/request/save"}, method = RequestMethod.POST)
    @ResponseBody
    public String save(RestApiRequest apiRequest) {
        apiRequest.setApiId(apiRequest.getApiId());
        apiRequest.setCreateDate(new Date());
        requestDao.save(apiRequest);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", BaseConstant.STATE_SUCCESS);
        return JSON.toJSONString(map);
    }

    /**
     * Description: 删除request
     * 
     * @param id
     * @param apiId
     * @return String
     * @see
     */
    @RequestMapping(value = {"/request/delete"}, method = RequestMethod.POST)
    @ResponseBody
    public String delete(Long id) {
        requestDao.delete(id);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", BaseConstant.STATE_SUCCESS);
        return JSON.toJSONString(map);
    }

    /**
     * Description: 更新request
     * 
     * @param id
     * @param code
     * @param description
     * @param location
     * @param type
     * @param isMust
     * @param condition
     * @return Object
     * @see
     */
    @RequestMapping(value = {"/request/update"}, method = RequestMethod.POST)
    @ResponseBody
    public Object update(RestApiRequest restApiRequest) {
        requestDao.save(restApiRequest);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", BaseConstant.STATE_SUCCESS);
        map.put("message", "更新成功");
        map.put("request", restApiRequest);
        return JSON.toJSONString(map);
    }

    /**
     * Description: rowkey设计
     * 
     * @param rowKey
     * @return Object
     * @see
     */
    @RequestMapping(value = {"/request/rowkey"})
    public Object rowkey(RowKey rowKey) {
        rowKeyDao.save(rowKey);
        return "redirect:/api/{apiId}/request/detail";
    }

    /**
     * Description: ajax加载response数据
     * 
     * @param apiId
     * @return Object
     * @see
     */
    @RequestMapping(value = {"/response/list"})
    @ResponseBody
    public Object load(Long apiId) {
        Map<String, Object> map = new HashMap<String, Object>();
        RestApi api = apiDao.findOne(apiId);
        Project project = projectDao.findOne(api.getProId());
        List<RestApiResponse> list = responseDao.findByApiIdOrderByColumnNameAsc(apiId);
        map.put("code", BaseConstant.STATE_SUCCESS);
        map.put("responseList", list);
        map.put("project", project);
        return JSON.toJSONString(map);
    }

    /**
     * Description: ajax保存response
     * 
     * @param apiId
     * @param code
     * @param description
     * @param columnName
     * @param type
     * @return Object
     * @see
     */
    @RequestMapping(value = {"/response/save"}, method = RequestMethod.POST)
    @ResponseBody
    public Object save(RestApiResponse apiResponse, @PathVariable Long apiId) {
        responseDao.save(apiResponse);
        List<RestApiResponse> nodeList = JsonUtils.toObject(apiResponse.getChildrenList(),
            new TypeReference<List<RestApiResponse>>() {});
        for (RestApiResponse restApiResponse : nodeList) {
            restApiResponse.setTopId(apiResponse.getId());
            responseDao.save(restApiResponse);
        }

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("responseId", apiResponse.getId());
        map.put("code", BaseConstant.STATE_SUCCESS);
        return JSON.toJSONString(map);
    }

    /**
     * Description: 更新前查response
     * 
     * @param rootPoint
     * @return Object
     * @see
     */
    @RequestMapping(value = {"/response/updatePre"})
    @ResponseBody
    public Object updatePre(Long responseId) {
        Map<String, Object> map = new HashMap<String, Object>();
        RestApiResponse response = responseDao.findOne(responseId);
        List<RestApiResponse> nodeList = responseDao.findByTopIdOrderByNodeIdAsc(responseId);
        if (!StringUtils.isEmpty(response) && !StringUtils.isEmpty(nodeList)) {
            map.put("code", BaseConstant.STATE_SUCCESS);
            map.put("response", response);
            map.put("nodeList", nodeList);
        }
        else {
            map.put("code", BaseConstant.STATE_NOFOUND);
        }

        return JSON.toJSONString(map);
    }

    /**
     * Description: 更新response
     * 
     * @param id
     * @param code
     * @param description
     * @param columnName
     * @param type
     * @return Object
     * @see
     */
    @RequestMapping(value = {"/response/update"}, method = RequestMethod.POST)
    @ResponseBody
    public Object updateResponse(RestApiResponse response) {
        List<RestApiResponse> nodeList = JsonUtils.toObject(response.getChildrenList(),
            new TypeReference<List<RestApiResponse>>() {});
        responseDao.deleteByTopId(response.getId());
        responseDao.save(nodeList);
        responseDao.save(response);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", BaseConstant.STATE_SUCCESS);
        map.put("message", "更新成功");
        map.put("response", response);
        return JSON.toJSONString(map);
    }

    /**
     * Description: 删除response
     * 
     * @param id
     * @return Object
     * @see
     */
    @RequestMapping(value = {"/response/delete"}, method = RequestMethod.POST)
    @ResponseBody
    public Object deleteResponse(Long id) {
        Map<String, Object> map = new HashMap<String, Object>();
        responseDao.delete(id);
        responseDao.deleteByTopId(id);
        map.put("code", BaseConstant.STATE_SUCCESS);
        return JSON.toJSONString(map);
    }

    /**
     * Description: 重复校验request
     * 
     * @param code
     * @param apiId
     * @return Object
     * @see
     */
    @RequestMapping(value = {"/request/checkRequestCode"})
    @ResponseBody
    public Object checkRequestCode(String code, Long apiId) {

        RestApiRequest restApiRequest = requestDao.findByApiIdAndCode(apiId, code);
        Map<String, Object> map = new HashMap<String, Object>();
        if (!StringUtils.isEmpty(restApiRequest)) {
            map.put("code", BaseConstant.STATE_CHONGFU);
            map.put("message", "不可以重复！");
        }
        return map;

    }

    /**
     * Description: 重复校验 response
     * 
     * @param apiId
     * @param code
     * @return Object
     * @see
     */
    @RequestMapping(value = {"/request/checkResponseCode"})
    @ResponseBody
    public Object checkResponseCode(long apiId, String code) {
        RestApiResponse restApiResponse = responseDao.findByApiIdAndCode(apiId, code);
        Map<String, Object> map = new HashMap<String, Object>();
        if (!StringUtils.isEmpty(restApiResponse)) {
            map.put("code", BaseConstant.STATE_CHONGFU);
            map.put("message", "不可以重复！");
        }
        return map;
    }
    
    /**
     * 点击需要分页时新增两个参数
     * Description: 
     * 
     *@param apiId
     *@return Object
     *
     * @see
     */
    @RequestMapping(value = {"/request/addParam"}, method = RequestMethod.POST)
    @ResponseBody
    public Object addParam(Long apiId) {
        Map<String, Object> map = new HashMap<String, Object>();
        RestApi api = apiDao.findOne(apiId);
        String list = "list";
        RestApiRequest request1 = requestDao.findByApiIdAndDataType(apiId, "2");
        RestApiRequest request2 = requestDao.findByApiIdAndDataType(apiId, "1");
        if(api.getResponseDataType().equals(list)&&StringUtils.isEmpty(request1)&&StringUtils.isEmpty(request2)){
            RestApiRequest pageNum = new RestApiRequest();
            pageNum.setApiId(apiId);
            pageNum.setCode("pageNum");
            pageNum.setDescription("查询第几页");
            pageNum.setCreateDate(new Date());
            pageNum.setLocation("query");
            pageNum.setType("int");
            pageNum.setIsMust("true");
            pageNum.setDataType("2");
            
            RestApiRequest pageSize = new RestApiRequest();
            pageSize.setApiId(apiId);
            pageSize.setCode("pageSize");
            pageSize.setDescription("每页多少条");
            pageSize.setCreateDate(new Date());
            pageSize.setLocation("query");
            pageSize.setType("int");
            pageSize.setIsMust("true");
            pageSize.setDataType("1");

            requestDao.save(pageNum);
            requestDao.save(pageSize);
            map.put("code", BaseConstant.STATE_SUCCESS);
        }
        return map;
    }

    /**
     * 不选中时删除这俩个参数
     * Description: 
     * 
     *@param apiId
     *@return Object
     *
     * @see
     */
    @RequestMapping(value = {"/request/deleteParam"}, method = RequestMethod.POST)
    @ResponseBody
    public Object deleteParam(Long apiId) {
        Map<String, Object> map = new HashMap<String, Object>();
        RestApiRequest pageNum = requestDao.findByApiIdAndDataType(apiId, "2");
        RestApiRequest pageSize = requestDao.findByApiIdAndDataType(apiId, "1");
        if(!StringUtils.isEmpty(pageNum)){
            requestDao.delete(pageNum);
        }
        if(!StringUtils.isEmpty(pageSize)){
            requestDao.delete(pageSize);
        }
        map.put("code", BaseConstant.STATE_SUCCESS);
        return map;
    }
    
    /**
     * 
     * Description: 
     * 
     *@param apiId
     *@return Object
     *
     * @see
     */
    @RequestMapping(value = {"/response/sqlDesign"}, method = RequestMethod.POST)
    @ResponseBody
    public Object sqlDesign(SqlSentence sqlSentence) {
        sqlDao.save(sqlSentence);
        Map<String,Object> map = new HashMap<>();
        map.put("code", BaseConstant.STATE_SUCCESS);
        return map;
    }
}
